"""
AI历史消息记忆管理数据库模型
"""

import json
from datetime import datetime
from typing import Optional, Dict, Any, List

from sqlalchemy import String, Text, DateTime, BigInteger, SmallInteger, JSON, Index, ForeignKey
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.sql import func

from config.database import Base


class AIWebMemoryHisModel(Base):
    """AI历史消息记忆管理数据库模型"""
    __tablename__ = "ai_web_memory_his"

    # 主键
    id: Mapped[int] = mapped_column(
        BigInteger().with_variant(BigInteger, "mysql"),
        primary_key=True,
        autoincrement=True,
        comment="自增主键，唯一标识每条历史消息"
    )

    # 核心关联字段
    scene_id: Mapped[str] = mapped_column(
        String(64),
        ForeignKey("ai_web_scene.scene_id"),
        nullable=False,
        comment="场景 ID，用于区分不同应用场景"
    )
    agent_id: Mapped[str] = mapped_column(
        String(64),
        ForeignKey("ai_web_agent.agent_id"),
        nullable=False,
        comment="智能体 ID，标识处理消息的 AI 主体"
    )
    session_id: Mapped[str] = mapped_column(
        String(64),
        nullable=False,
        comment="对话 ID，关联同一次对话的所有消息"
    )
    user_id: Mapped[str] = mapped_column(
        String(64),
        nullable=False,
        comment="用户 ID，标识消息所属用户"
    )

    # 内容字段
    his_text: Mapped[str] = mapped_column(
        Text,
        nullable=False,
        comment="历史消息内容，支持长文本存储"
    )

    # 时间字段
    create_time: Mapped[datetime] = mapped_column(
        DateTime,
        nullable=False,
        default=func.now(),
        comment="消息创建时间，自动记录消息生成时间"
    )
    update_time: Mapped[Optional[datetime]] = mapped_column(
        DateTime,
        nullable=True,
        onupdate=func.now(),
        comment="最后更新时间，标注或状态变更时更新"
    )

    # 状态和分类字段
    status: Mapped[int] = mapped_column(
        SmallInteger,
        nullable=False,
        default=1,
        comment="状态标识：1 = 临时 / 2 = 当天 / 3 = 永久，默认 1"
    )
    importance_level: Mapped[int] = mapped_column(
        SmallInteger,
        nullable=False,
        default=3,
        comment="重要程度：1-5 级，默认 3"
    )

    # 标记和扩展字段
    tags: Mapped[Optional[str]] = mapped_column(
        String(255),
        nullable=True,
        comment="自定义标签，多个标签用逗号分隔"
    )
    annotation: Mapped[Optional[str]] = mapped_column(
        Text,
        nullable=True,
        comment="标注内容，用户对消息的备注或说明"
    )
    extra_info: Mapped[Optional[str]] = mapped_column(
        JSON,
        nullable=True,
        comment="扩展信息，存储 JSON 格式的附加数据"
    )

    # 关联关系
    scene: Mapped[Optional["AIWebSceneModel"]] = relationship(
        "AIWebSceneModel",
        back_populates="memories",
        lazy="select"
    )
    agent: Mapped[Optional["AIWebAgentModel"]] = relationship(
        "AIWebAgentModel",
        back_populates="memories",
        lazy="select"
    )

    # 索引定义
    __table_args__ = (
        Index('idx_scene_id', 'scene_id'),
        Index('idx_agent_id', 'agent_id'),
        Index('idx_session_id', 'session_id'),
        Index('idx_user_id', 'user_id'),
        Index('idx_create_time', 'create_time'),
        Index('idx_update_time', 'update_time'),
        {"comment": "AI历史消息记忆管理表"}
    )

    def __repr__(self):
        return f"<AIWebMemoryHisModel(id={self.id}, scene_id='{self.scene_id}', session_id='{self.session_id}', status={self.status})>"

    def to_dict(self) -> dict:
        """转换为字典"""
        return {
            "id": self.id,
            "scene_id": self.scene_id,
            "agent_id": self.agent_id,
            "session_id": self.session_id,
            "user_id": self.user_id,
            "his_text": self.his_text,
            "create_time": self.create_time.isoformat() if self.create_time else None,
            "update_time": self.update_time.isoformat() if self.update_time else None,
            "status": self.status,
            "importance_level": self.importance_level,
            "tags": self.tags,
            "annotation": self.annotation,
            "extra_info": self.get_extra_info()
        }

    def get_extra_info(self) -> Optional[Dict[str, Any]]:
        """获取扩展信息"""
        if isinstance(self.extra_info, str):
            try:
                return json.loads(self.extra_info)
            except (json.JSONDecodeError, TypeError):
                return None
        return self.extra_info

    def set_extra_info(self, extra_info: Optional[Dict[str, Any]]) -> None:
        """设置扩展信息"""
        if extra_info:
            self.extra_info = json.dumps(extra_info, ensure_ascii=False)
        else:
            self.extra_info = None

    def get_tags_list(self) -> List[str]:
        """获取标签列表"""
        if self.tags:
            return [tag.strip() for tag in self.tags.split(',') if tag.strip()]
        return []

    def set_tags_list(self, tags_list: List[str]) -> None:
        """设置标签列表"""
        if tags_list:
            # 过滤空标签并去重
            filtered_tags = list(dict.fromkeys([tag.strip() for tag in tags_list if tag.strip()]))
            self.tags = ','.join(filtered_tags)
        else:
            self.tags = None

    def add_tag(self, tag: str) -> None:
        """添加标签"""
        if not tag or not tag.strip():
            return

        current_tags = self.get_tags_list()
        tag = tag.strip()

        if tag not in current_tags:
            current_tags.append(tag)
            self.set_tags_list(current_tags)

    def remove_tag(self, tag: str) -> None:
        """移除标签"""
        if not tag or not tag.strip():
            return

        current_tags = self.get_tags_list()
        tag = tag.strip()

        if tag in current_tags:
            current_tags.remove(tag)
            self.set_tags_list(current_tags)

    def has_tag(self, tag: str) -> bool:
        """检查是否包含指定标签"""
        if not tag or not tag.strip():
            return False
        return tag.strip() in self.get_tags_list()

    def is_temporary(self) -> bool:
        """判断是否为临时消息"""
        return self.status == 1

    def is_daily(self) -> bool:
        """判断是否为当天消息"""
        return self.status == 2

    def is_permanent(self) -> bool:
        """判断是否为永久消息"""
        return self.status == 3

    def is_high_importance(self) -> bool:
        """判断是否为高重要性消息（4级及以上）"""
        return self.importance_level >= 4

    def is_low_importance(self) -> bool:
        """判断是否为低重要性消息（2级及以下）"""
        return self.importance_level <= 2

    def update_status(self, new_status: int) -> None:
        """更新状态"""
        # 验证status值
        if not isinstance(new_status, int):
            if isinstance(new_status, str):
                try:
                    new_status = int(new_status)
                except ValueError:
                    raise ValueError(f"无效的状态值: {new_status}，必须是 1, 2, 3 中的一个")
            else:
                raise ValueError(f"状态值必须是整数，当前类型: {type(new_status)}")

        if new_status not in [1, 2, 3]:
            raise ValueError(f"无效的状态值: {new_status}，必须是 1, 2, 3 中的一个")

        self.status = new_status
        self.update_time = datetime.now()

    def update_importance(self, new_importance: int) -> None:
        """更新重要程度"""
        # 验证importance_level值
        if not isinstance(new_importance, int):
            if isinstance(new_importance, str):
                try:
                    new_importance = int(new_importance)
                except ValueError:
                    raise ValueError(f"无效的重要程度: {new_importance}，必须是 1-5 之间的数字")
            else:
                raise ValueError(f"重要程度必须是整数，当前类型: {type(new_importance)}")

        if not (1 <= new_importance <= 5):
            raise ValueError(f"无效的重要程度: {new_importance}，必须是 1-5 之间的数字")

        self.importance_level = new_importance
        self.update_time = datetime.now()

    def update_annotation(self, annotation: Optional[str]) -> None:
        """更新标注内容"""
        self.annotation = annotation
        self.update_time = datetime.now()

    def promote_to_permanent(self) -> None:
        """提升为永久消息"""
        self.update_status(3)

    def demote_to_temporary(self) -> None:
        """降级为临时消息"""
        self.update_status(1)

    def set_as_daily(self) -> None:
        """设置为当天消息"""
        self.update_status(2)

    def get_age_in_days(self) -> int:
        """获取消息存在天数"""
        if self.create_time:
            delta = datetime.now() - self.create_time
            return delta.days
        return 0

    def is_expired(self, temp_days: int = 1, daily_days: int = 7) -> bool:
        """判断消息是否过期（根据状态和时间判断）"""
        age_days = self.get_age_in_days()

        if self.is_temporary():
            return age_days > temp_days
        elif self.is_daily():
            return age_days > daily_days
        else:  # 永久消息不过期
            return False

    def should_archive(self, archive_threshold_days: int = 30) -> bool:
        """判断是否应该归档（基于创建时间）"""
        return self.get_age_in_days() > archive_threshold_days

    def get_summary(self, max_length: int = 100) -> str:
        """获取消息摘要"""
        if len(self.his_text) <= max_length:
            return self.his_text
        return self.his_text[:max_length] + "..."

    def contains_keyword(self, keyword: str) -> bool:
        """检查消息内容是否包含关键词"""
        if not keyword:
            return True
        keyword = keyword.lower()
        return (keyword in self.his_text.lower() or
                (self.annotation and keyword in self.annotation.lower()) or
                (self.tags and keyword in self.tags.lower()))

    def get_display_status(self) -> str:
        """获取状态显示文本"""
        status_map = {1: "临时", 2: "当天", 3: "永久"}
        return status_map.get(self.status, "未知")

    def get_display_importance(self) -> str:
        """获取重要程度显示文本"""
        importance_map = {1: "很低", 2: "低", 3: "中等", 4: "高", 5: "很高"}
        return importance_map.get(self.importance_level, "未知")
